/**
 * @Question.Title: 粉刷房子 III
 * @Question.No: 1473
 * @Author: Dang Qi
 * @Date: 2021-05-04 08:15:06
 * @Description: 
 */
//在一个小城市里，有 m 个房子排成一排，你需要给每个房子涂上 n 种颜色之一（颜色编号为 1 到 n ）。有的房子去年夏天已经涂过颜色了，所以这些房子不需要
//被重新涂色。 
//
// 我们将连续相同颜色尽可能多的房子称为一个街区。（比方说 houses = [1,2,2,3,3,2,1,1] ，它包含 5 个街区 [{1}, {2,2}
//, {3,3}, {2}, {1,1}] 。） 
//
// 给你一个数组 houses ，一个 m * n 的矩阵 cost 和一个整数 target ，其中： 
//
// 
// houses[i]：是第 i 个房子的颜色，0 表示这个房子还没有被涂色。 
// cost[i][j]：是将第 i 个房子涂成颜色 j+1 的花费。 
// 
//
// 请你返回房子涂色方案的最小总花费，使得每个房子都被涂色后，恰好组成 target 个街区。如果没有可用的涂色方案，请返回 -1 。 
//
// 
//
// 示例 1： 
//
// 输入：houses = [0,0,0,0,0], cost = [[1,10],[10,1],[10,1],[1,10],[5,1]], m = 5, n
// = 2, target = 3
//输出：9
//解释：房子涂色方案为 [1,2,2,1,1]
//此方案包含 target = 3 个街区，分别是 [{1}, {2,2}, {1,1}]。
//涂色的总花费为 (1 + 1 + 1 + 1 + 5) = 9。
// 
//
// 示例 2： 
//
// 输入：houses = [0,2,1,2,0], cost = [[1,10],[10,1],[10,1],[1,10],[5,1]], m = 5, n
// = 2, target = 3
//输出：11
//解释：有的房子已经被涂色了，在此基础上涂色方案为 [2,2,1,2,2]
//此方案包含 target = 3 个街区，分别是 [{2,2}, {1}, {2,2}]。
//给第一个和最后一个房子涂色的花费为 (10 + 1) = 11。
// 
//
// 示例 3： 
//
// 输入：houses = [0,0,0,0,0], cost = [[1,10],[10,1],[1,10],[10,1],[1,10]], m = 5, 
//n = 2, target = 5
//输出：5
// 
//
// 示例 4： 
//
// 输入：houses = [3,1,2,3], cost = [[1,1,1],[1,1,1],[1,1,1],[1,1,1]], m = 4, n = 3
//, target = 3
//输出：-1
//解释：房子已经被涂色并组成了 4 个街区，分别是 [{3},{1},{2},{3}] ，无法形成 target = 3 个街区。
// 
//
// 
//
// 提示： 
//
// 
// m == houses.length == cost.length 
// n == cost[i].length 
// 1 <= m <= 100 
// 1 <= n <= 20 
// 1 <= target <= m 
// 0 <= houses[i] <= n 
// 1 <= cost[i][j] <= 10^4 
// 
// Related Topics 动态规划 
// 👍 59 👎 0

package dq.leetcode.editor.cn;

import com.dq.utils.CreateArray;

import java.util.Arrays;

public class PaintHouseIii {
    public static void main(String[] args) {
        Solution solution = new PaintHouseIii().new Solution();
        int[] houses = {0,0,0,0,0};
        int[][] cost = (int[][]) CreateArray.genIntArray("[[1,10],[10,1],[10,1],[1,10],[5,1]]");
        int m = 5;
        int n = 2;
        int target = 3;
        System.out.println(solution.minCost(houses, cost, m, n, target));
    }
        //leetcode submit region begin(Prohibit modification and deletion)
class Solution {
    public int minCost(int[] houses, int[][] cost, int m, int n, int target) {
        /** dp[i][j][k] 表示第i个房子，凃有颜色j，并且前i个房子中有k个邻域
         *  dp[i][j][k] 表示最小代价
         *  j > 0, k > 0
         */
        int[][][] dp = new int[m][n+1][target+1];
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                Arrays.fill(dp[i][j], Integer.MAX_VALUE);
            }
        }
        //所有房子
        for(int i = 0; i < m; i++){
            //所有颜色
            for(int j = 1; j <= n; j++){
                //cs 表示将当前这个涂成j颜色需要的花费
                int cs = houses[i]==j ? 0: cost[i][j-1];
                if(i==0){
                    dp[i][j][1] = cs;
                    continue;
                }
                for(int k = 1; k <= target; k++){
                    dp[i][j][k] = dp[i-1][j][k] + cs;
                    for(int j2 = 1; j2 <= n; j2++){
                        if(j2==j) continue;
                        dp[i][j][k] = Math.min(dp[i-1][j2][k-1] + cs, dp[i][j][k]);
                    }
                }
            }
        }


        return dp[m-1][n][target];
    }
}
//leetcode submit region end(Prohibit modification and deletion)

}